import { Component,  Input, EventEmitter, Output} from '@angular/core';
import { ElementRef } from '@angular/core';
@Component({
  selector: 'my-canvas',
  templateUrl: 'my-canvas.html',
  styleUrls: ['my-canvas.less'],
})
export class MyCanvas {


  @Input() setData: any;
  @Input() setKey: any;

  constructor(private el: ElementRef) {
  };

  ngOnChanges(): void {
  
    this.copyKeyData=this.setKey;
    this.data=this.setData;

    this.canvasInit();
    window.addEventListener('resize', () => {
      this.ResetCanvas();
      this.canvasDraw();
    });
    document.addEventListener('click',() => {
      let delDom = this.el.nativeElement.querySelector('.Headscreen');
      if (delDom&&this.delDomShow) {
        delDom.style.display="none"
      };
    })
    this.el.nativeElement.style.display = 'block';
    this.el.nativeElement.style.position = 'relative';
  };

  // ngOnChanges(): void {
  //   //Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.
  //   //Add '${implements OnChanges}' to the class.
    
  // }

  dateStart='';
  dateEnd='';
  actSortsSpan="default"; // Upward  down
  config = {
    DownloadCsv: true,
  };
  Ctx = null;
  data = [];
  copyKeyData = [
    { key: 'id', Width: 50, headAlign: 'center', textAlign: 'left', text: '编号', isdownload: true, type: 'str' },
    { key: 'type', Width: 100, headAlign: 'left', textAlign: 'center', text: '类型', isdownload: true, type: 'str' },
    { key: 'name', Width: 200, headAlign: 'right', textAlign: 'right', text: '名称', isdownload: true, type: 'str' },
    { key: 'start', Width: null, headAlign: 'right', textAlign: 'center', text: '开始', isdownload: true, type: 'date' },
    { key: 'money', Width: null, headAlign: 'right', textAlign: 'right', text: '金额', isdownload: true, type: 'money' },
    { key: 'number', Width: null, headAlign: 'right', textAlign: 'right', text: '数值', isdownload: true, type: 'number', whileMin: 1, whileMax: 10, whileInterval: 'left' } //whileInterval:'left','right','center','twoEnds'
  ];
  key_data = [
    // { key: 'id', Width: 50, headAlign: 'center', textAlign: 'left', text: '编号' ,isdownload:true},
    // { key: 'type', Width: 100, headAlign: 'left', textAlign: 'center', text: '类型',isdownload:true },
    // { key: 'name', Width: 200, headAlign: 'right', textAlign: 'right', text: '名称',isdownload:true },
    // { key: 'start', Width: null, headAlign: 'right', textAlign: 'center', text: '开始',isdownload:true },
    // { key: 'money', Width: null, headAlign: 'right', textAlign: 'center', text: '金额',isdownload:true }
  ];
  data_xy = [];
  totalDate = []; // 合计值
  AbnormalArr = []; //异常数据合计
  linSearchData = []; //搜索条件集合
  headRowColumn = {
    RowHeight: 30,
    isClcik: false, //点击列头
  };
  footRowColumn = {
    RowHeight: 30,
    isClcik: false, //点击列头
  };
  dataRowColumn = {
    RowWidth: 20,//行宽
    RowHeight: 20,//行高
    isRowClcik: false, //点击行
  };
  //选中的单元格数据
  lastCell = {
    X: null,
    Y: null,
    Width: null,
  };
  actCellArr = [];
  //选中的行数据
  actRowArr = [];
  lastRow = {};
  /**
  * @param `mouseSeart_X` 鼠标按下X坐标
  * @param `mouseSeart_Y` 鼠标按下Y坐标
  * @param `mouseEnd_X`   鼠标松开X坐标
  * @param `mouseEnd_Y`   鼠标松开Y坐标
  */
  mouse_XY = {
    mouseSeart_X: null,
    mouseSeart_Y: null,
    mouseEnd_X: null,
    mouseEnd_Y: null,
  }
  /**
   * @param `actSeart_X` 鼠标按下对象X坐标
   * @param `actSeart_Y` 鼠标按下对象Y坐标
   * @param `actEnd_X`   鼠标松开对象X坐标
   * @param `actEnd_Y`   鼠标松开对象Y坐标
   */
  act_lin = {
    actSeart_X: null,
    actSeart_Y: null,
    actSeart_EX: null,
    actSeart_EY: null,
    actEnd_X: null,
    actEnd_Y: null,
    actEnd_W: 0,
  };

  /**
   * 画布数据
 * @param `canH`          整体高度
 * @param `contenW`       可展示区域宽度
 */
  canWH = {
    canH: 0,
    canW: 0,
    contenW: 0,
    contenH: 0,  //画布内容最大高度
  }
  /**
   *  鼠标对象数据
   *  @param `isMousedown`      鼠标是否按下 
   *  @param `mousedownX`       鼠标按下在画布上的X坐标位置
   *  @param `mousedownY`       鼠标按下在画布上的Y坐标位置 
   * */
  mouseData = {
    mousedowTime: 0,      //鼠标按下的开始时间
    isMousedown: false,   //鼠标按下
    mousedownX: 0,       //鼠标按下在画布上的X坐标位置
    mousedownY: 0,       //鼠标按下在画布上的Y坐标位置 
    mouseupX: 0,         //鼠标松开在画布上的X坐标位置 
    mouseupY: 0,         //鼠标松开在画布上的Y坐标位置 
  };
  /**
   * 滚动条
  * @param `scrollRightX`      右侧Y轴滚动条X坐标位置
  * @param `scrollRightY`      右侧Y轴滚动条Y坐标位置
  * @param `scrollRightW`      右侧Y轴滚动条的宽度
  * @param `scrollBottomW`     底部X轴滚动条的宽度
  * @param `scrollBottomX`     底部X轴滚动条X坐标位置
  * @param `scrollBottomY`     底部X轴滚动条Y坐标位置
  **/
  scrollPosition = {
    scrollRightX: 0,
    scrollRightY: 0,
    scrollRightW: 20,  //右侧Y轴滚动条的宽度
    scrollRightH: 30,
    scrollRightHover: false,
    scrollRightClick: false,

    scrollBottomX: 0,
    scrollBottomY: 0,
    scrollBottomW: 0,
    scrollBottomH: 0,
    scrollBottomHover: false,
  }
  /**
   * @param `index`       当前数据页数
   * @param `scrollTop`   滚动条距离顶部的距离
   * @param `width`       可展示区域宽度
   * @param `height`      可展示区域高度
   */
  canPaeg = {
    index: 0,
    scrollTop: 0,
    width: 0,
    height: 0 // 可展示区域高度
  };

  //初始化 只算一次数值
  canvasInit() {
    let start_time = new Date().getTime();
    let can = this.el.nativeElement.querySelector('canvas');
    
    let scrollHeight = can.parentNode.parentNode.scrollHeight;
    let scrollWidth = can.parentNode.parentNode.scrollWidth;
    can.width = 0;
    can.height = 0;
    this.canPaeg.width = 0;
    this.canPaeg.height = 0;

    can.width = scrollWidth;
    can.height = scrollHeight;

    can.style.background = '#fff';
    this.canPaeg.width = scrollWidth;
    this.canPaeg.height = scrollHeight;

    this.headRowColumn.RowHeight = 30;
    this.canWH.contenH = 0;
    console.log('获取对象，设置宽高', new Date().getTime() - start_time);
    this.data.forEach(item => {
      item['__row'] = "";
      this.canWH.contenH += this.dataRowColumn.RowHeight;
    });
    if (this.footRowColumn.RowHeight) {
      this.canWH.contenH += this.footRowColumn.RowHeight;
    }
    console.log('渲染页面总高度', new Date().getTime() - start_time);
    this.key_data = this.headDealWith(this.copyKeyData);
    console.log('计算页头参数', new Date().getTime() - start_time);
    let scroll_conH = this.canPaeg.height - this.headRowColumn.RowHeight - this.footRowColumn.RowHeight;
    let s_H = scroll_conH * (scroll_conH / this.canWH.contenH);
    this.scrollPosition.scrollRightH = s_H > 5 ? s_H : 5; //设置滚动条高度
    this.Ctx = can.getContext('2d');
    let YY = this.canPaeg.scrollTop / (this.canWH.contenH) * (this.canPaeg.height - 30);
    this.scrollPosition.scrollRightY = YY + this.headRowColumn.RowHeight;
    let opt = this.FormatData(this.key_data, this.data);
    console.log('处理数据，异常数据', new Date().getTime() - start_time);
    this.data_xy = opt.data_xy;
    this.AbnormalArr = opt.AbnormalArr;
    console.log('赋值数据，异常数据', new Date().getTime() - start_time);
    this.totalDate = [];
    this.data_xy.forEach((e, i) => {
      let text = this.Calculate_total(e.data, this.key_data[i]);
      this.key_data[i]['total'] = text;
      this.totalDate.push(text);
    });
    console.log('计算页头合计数', new Date().getTime() - start_time);
    this.addSeachLise(this.key_data,this.data_xy);
    this.canvasDraw();
    // let =new Date().getTime();
    console.log('渲染时间', new Date().getTime() - start_time);
  }

  /**
   * 处理列头
   * @param headData 原始列头数组
   * cshlist
   */
  headDealWith(headData) {
    let width = 0;
    let no_width = 0;
    let keData = [];
    keData = [{ key: '__row', Width: 15, headAlign: 'center', textAlign: 'left', text: '', isdownload: false }].concat(headData);
    keData.forEach(item => {
      if (!item.Width) {
        no_width++;
      } else {
        width += (item.Width ? item.Width : 0);
      }
    });
    let arr = [];
    keData.forEach((item, i) => {
      let opt: any = {}
      for (let n in item) {
        opt[n] = item[n];
      }
      if (!item.Width) {
        opt['Width'] = Math.round((this.canPaeg.width - width - this.scrollPosition.scrollRightW) / no_width);
      }
      arr.push(opt);
    });
    let lin_X = 0.5;
    arr.forEach(item => {
      item['X'] = lin_X;
      lin_X += item.Width;
    })
    return arr
  }

  //重绘图形 数据不变
  ResetCanvas() {
    this.key_data = this.headDealWith(this.copyKeyData);
    let opt = this.FormatData(this.key_data, this.data);
    this.data_xy = opt.data_xy;
    this.AbnormalArr = opt.AbnormalArr;
    this.canWH.contenH = 0;
    this.data_xy[0].data.forEach(item => {
      item['__row'] = "";
      this.canWH.contenH += this.dataRowColumn.RowHeight;
    });
    if (this.footRowColumn.RowHeight) {
      this.canWH.contenH += this.footRowColumn.RowHeight;
    }
    let scroll_conH = this.canPaeg.height - this.headRowColumn.RowHeight - this.footRowColumn.RowHeight;
    let s_H = scroll_conH * (scroll_conH / this.canWH.contenH);
    this.scrollPosition.scrollRightH = s_H > 5 ? s_H : 5; //设置滚动条高度

    let can = this.el.nativeElement.querySelector('canvas');
    can.width = 0;
    can.height = 0;
    this.canPaeg.width = 0;
    this.canPaeg.height = 0;
    let scrollHeight = can.parentNode.parentNode.scrollHeight;
    let scrollWidth = can.parentNode.parentNode.scrollWidth;

    can.width = scrollWidth;
    can.height = scrollHeight;

    can.style.background = '#fff';
    this.canPaeg.width = scrollWidth;
    this.canPaeg.height = scrollHeight;
    this.headRowColumn.RowHeight = 30;

    this.actCellArr.forEach(item => {
      item.Width = this.key_data[item.lin].Width;
      item.X = this.key_data[item.lin].X;
    });


  }

  /** 
   *处理原始数据
   * */
  FormatData(keys, datas) {
    let arrs = [];
    datas = [...datas.filter(data => {
      let is_p = true; 
      this.linSearchData.forEach(item => {
        if (item) {
          if(item.type=='str'){
            if(item.list.length>0){ //类型按条件筛选
              is_p=item.list.includes(data[item.key]);
            }else if(item.searchInput){ // 文字类型 按输入内容模糊查询
              is_p = !is_p ? is_p : data[item.key].includes(item.searchInput);
            }
          }
          if(item.type=='date'&&(item.dateStart||item.dateEnd)){
            let dataDate=new Date(data[item.key]);
            if( dataDate instanceof Date){

              let startTime_=new Date(item.dateStart).getTime()?new Date(item.dateStart).getTime():0;
              let endTime_=new Date(item.dateEnd).getTime()?new Date(item.dateEnd).getTime():Infinity;
              let startTime=Math.min(startTime_,endTime_);
              let endTime=Math.max(startTime_,endTime_);
              is_p = (dataDate.getTime()>=startTime||isNaN(startTime))&&(dataDate.getTime()<=endTime||isNaN(endTime));
            }else{
              is_p =false;
            }
          }
        }
      });
      return is_p;
    })];

    this.linSearchData.forEach(item => {
      console.log('排序');
      if(item&&item.sorts!=='default'){
        console.log(item);
        datas.sort((a,b) => {
          if(item.type=='number'||item.type=='money'){
              if(item.sorts=='down'){ //正序
               return parseFloat(a[item.key]) - parseFloat(b[item.key]);
              }else{//倒序
                return parseFloat(b[item.key])-parseFloat(a[item.key]);
              } 
          }
        })
      }
    })

    // datas


    //判断是否是异常数值
    const isAbnormal = (key, data) => {
      if (!key.whileInterval) {
        return 'normal'
      }
      let whileMin = key.whileMin ? key.whileMin : 0,
        whileMax = key.whileMax ? key.whileMax : 0;
      // 'left','right','center','twoEnds'
      let num = parseFloat(data[key.key]);
      if (key.whileInterval == 'left' && num < whileMin) {
        return 'left'
      } else if (key.whileInterval == 'right' && num >= whileMax) {
        return 'right'
      } else if (key.whileInterval == 'center' && num <= whileMax && num > whileMin) {
        return 'center'
      } else if (key.whileInterval == 'twoEnds' && (num >= whileMax || num < whileMin)) {
        return 'twoEnds'
      } else {
        return 'normal'
      }
    };

    let AbnormalArr = [];
    let text_x = 0.5;
    let text_y = 31.5;
    this.data_xy = [];
    let RowHeight = this.dataRowColumn.RowHeight;
    let start_time = new Date().getTime();
    text_y = this.headRowColumn.RowHeight + 1.5;

    keys.forEach((item, lin) => {
      let arr = [];
      text_y = this.headRowColumn.RowHeight + 1.5;
      let linAbnormal = [];
      let start_time = new Date().getTime();

      datas.forEach((data, row) => {
        let isnormal = 'normal';
        if (item.whileInterval) {
          isnormal = isAbnormal(item, data);
          if (isnormal != "normal") {
            linAbnormal.push(row);
          };
        }
        arr.push({
          text: data[item.key],
          X: text_x,
          Y: text_y,
          key: item.key,
          Width: item.Width,
          lin: lin,
          row: row,
          isnormal: isnormal
        });
        text_y += RowHeight;
      });
      if (item.whileInterval) {
        AbnormalArr.push(linAbnormal);
      };
      arrs.push({
        X: text_x,
        W: item.Width,
        key: item.key,
        headAlign: item.headAlign,
        textAlign: item.textAlign,
        text: item.text,
        data: arr
      });
      text_x += item.Width;
    });

    return { data_xy: arrs, AbnormalArr: AbnormalArr };
  }
  /**
   * 绘制 图像
   **/
  canvasDraw() {
    let start_time = new Date().getTime();
    this.Ctx.clearRect(0, 0, this.canPaeg.width, this.canPaeg.height);
    let W = this.canWH.canW + this.canPaeg.width;
    let can_Top = this.canPaeg.scrollTop;
    this.canWH.canH;

    this.Ctx.strokeStyle = "#d1d1d1";
    this.Ctx.lineWidth = 1;
    let lin_y = 0.5;
    let lin_X = 0.5;

    this.Ctx.beginPath();
    this.Ctx.moveTo(0, lin_y);
    this.Ctx.lineTo(W, lin_y);
    this.Ctx.stroke();
    lin_y += 30;
    // 画线 行线
    this.data_xy[0].data.forEach(item => {
      if ((lin_y - can_Top) >= 0 && (lin_y - can_Top) <= this.headRowColumn.RowHeight + this.canPaeg.height) {
        this.Ctx.beginPath();
        this.Ctx.moveTo(0, lin_y - this.canPaeg.scrollTop);
        this.Ctx.lineTo(W, lin_y - this.canPaeg.scrollTop);
        this.Ctx.stroke();
      }
      lin_y += 20;
    })

    //画线 竖线
    this.Ctx.beginPath();
    this.Ctx.moveTo(0.5, 0);
    this.Ctx.lineTo(0.5, lin_y - this.canPaeg.scrollTop);
    this.Ctx.stroke();
    this.key_data.forEach(item => {
      this.Ctx.beginPath();
      this.Ctx.moveTo(item.X, 0);
      this.Ctx.lineTo(item.X, lin_y - this.canPaeg.scrollTop);
      this.Ctx.stroke();
    })

    this.Ctx.beginPath();
    this.Ctx.moveTo(W - 0.5, 0);
    this.Ctx.lineTo(W - 0.5, lin_y - this.canPaeg.scrollTop);
    this.Ctx.stroke();
    this.conten_Selection();
    if (this.actRowArr.length > 0) {
      this.drawRowSelected();
    }
    //插入文字
    //插入数据内容
    this.Ctx.textBaseline = 'top';
    this.Ctx.font = "14px serif";
    this.Ctx.fillStyle = "#000";

    const isInsideY = (data) => {
      let start = null;
      if(data.length==0){
        return 0
      }
      if (data[data.length - 1].Y >= this.canPaeg.scrollTop) {
        for (let n = 0; n < data.length; n++) {
          if (data[n].Y >= this.canPaeg.scrollTop) {
            start = n - 1;
            break;
          }
        }
        return start >= 0 ? start : 0;
      } else {
        return 'next';
      }
    };
    let start_y = 0;
    start_y = isInsideY(this.data_xy[0].data);
    let end_y = start_y + Math.ceil(this.canPaeg.height / this.dataRowColumn.RowHeight);
    this.data_xy.forEach(linX => {
      let arr = linX.data.slice(start_y, end_y);
      arr.forEach(linY => {
        if (linY.isnormal != 'normal') { //判断是否是异常数据
          this.Ctx.fillStyle = "rgba(247, 25, 25, 0.34)";
          this.Ctx.fillRect(linY.X, linY.Y - 0.5 - this.canPaeg.scrollTop, linX.W, this.dataRowColumn.RowHeight)
        }
        this.Ctx.fillStyle = "#000";
        this.Ctx.textAlign = linX.textAlign;
        if (linX.textAlign == 'center') {
          this.Ctx.fillText(linY.text, linY.X + linX.W / 2, linY.Y - can_Top);
        } else if (linX.textAlign == 'right') {
          this.Ctx.fillText(linY.text, linY.X + linX.W - 5, linY.Y - can_Top);
        } else {
          this.Ctx.fillText(linY.text, linY.X + 2, linY.Y - can_Top);
        }
      });
    })

    //绘制列头
    this.scrollPosition.scrollRightX = this.canPaeg.width - this.scrollPosition.scrollRightW;
    this.Draw_scroll(this.scrollPosition.scrollRightX, this.scrollPosition.scrollRightY, this.scrollPosition.scrollRightW, this.scrollPosition.scrollRightH, this.AbnormalArr);
    this.DrawHead();
    this.footDraw();
    this.DownloadCsvDraw(1, 2);
  }


  /**
   * 绘制表头
   * @param 
   */
  DrawHead() {
    let key_linX = 0.5;
    this.Ctx.font = "16px serif";
    this.Ctx.strokeStyle = "#d3d3d3";
    this.Ctx.fillStyle = "#000";
    this.Ctx.textBaseline = 'middle'; //上下对齐方式
    this.key_data.forEach(item => {
      this.Ctx.fillStyle = "#f3f3f3";
      this.Ctx.fillRect(key_linX, 0.5, item.Width, this.headRowColumn.RowHeight);
      this.Ctx.fillStyle = "#000";
      this.Ctx.strokeRect(key_linX, 0.5, item.Width, this.headRowColumn.RowHeight);
      this.Ctx.fillStyle = "#000";
      this.Ctx.textAlign = item.headAlign;
      if (item.headAlign == 'center') {
        this.Ctx.fillText(item.text, key_linX + item.Width / 2, (this.headRowColumn.RowHeight / 2));
      } else if (item.headAlign == 'right') {
        this.Ctx.fillText(item.text, key_linX + item.Width - 2, (this.headRowColumn.RowHeight / 2));
      } else {
        this.Ctx.fillText(item.text, key_linX + 2, (this.headRowColumn.RowHeight / 2));
      }
      key_linX += item.Width;
    });
  }


  /**
   * 鼠标按下事件
   * @param `e` event对象
   * 确定起始位置 区域
   **/
  mousedownCanvas(e) {
    if (e.which != 1) { //左击鼠标事件
      return
    };
    this.mouseData.mousedowTime = new Date().getTime();
    this.mouseData.isMousedown = true;
    this.mouseData.mousedownX = e.offsetX;
    this.mouseData.mousedownY = e.offsetY;

    this.act_lin.actSeart_X = e.offsetX;
    this.act_lin.actSeart_Y = e.offsetY + this.canPaeg.scrollTop;
    if (this.isHoverscrollRight(e)) {//判断是否点击滚动条区域
      this.scrollPosition.scrollRightClick = true;
    } else if (this.isMouseHead(e.offsetX, e.offsetY)) { //判断是否点击列头区域
      this.headRowColumn.isClcik = true;
    } else if (this.isRowLeft(e)) { //判断是否再左侧第一列
      this.actCellArr = [];
      this.dataRowColumn.isRowClcik = true;
    } else if (this.config.DownloadCsv && this.isDownloadCsv(e)) {
      console.log('点击了下载')
      this.downloadCsv();
    } else {
      this.actRowArr = [];
    }
  }
  // 

  /**
  * 鼠标在画布上移动事件
  * @param `e` event对象
  **/
  mousemoveCanvas(e) {
    this.act_lin.actEnd_Y = e.offsetY + this.canPaeg.scrollTop;
    if (this.mouseData.isMousedown) { //鼠标点击
      if (this.scrollPosition.scrollRightClick) { //点击滚动条
        this.el.nativeElement.style.cursor = "pointer";
        this.mousemoveScroll(e);
      } else if (this.headRowColumn.isClcik) { //列头
        console.log('列头移动')
      } else if (this.dataRowColumn.isRowClcik) { //选中行滑动
        console.log('选中行滑动');
        this.getRowSelectedData(e);
      } else {
        this.getDataConstituency(e);
      }
    } else {
      if (this.isHoverscrollRight(e)) { //判断鼠标是否在滚动条上cursor:pointer;
        this.el.nativeElement.style.cursor = "pointer";
      } else {
        this.el.nativeElement.style.cursor = "auto";
        if (this.scrollPosition.scrollRightHover) {
          this.scrollPosition.scrollRightHover = false;
          // this.scrollPosition.scrollRightW = 10;
          this.Ctx.clearRect(0, 0, this.canPaeg.width, this.canPaeg.height);
          this.canvasDraw();
        }
      }
    }
  }



  /**
   * 右击鼠标事件
   * @param `e` event对象
   * 确定松开位置判断 区域
   **/
  contextmenuCanvas() {
    console.log('右击鼠标事件')
  }


  /**
   * 点击事件
   * @param `e` event对象
   * 确定松开位置判断 区域
   **/
  clickCanvas(e) {
    this.mouseData.mouseupX = e.offsetX;
    this.mouseData.mouseupY = e.offsetY;
    let a = 1;
    if (!e.shiftKey) {
      this.lastCell.X = e.offsetX;
      this.lastCell.Y = e.offsetY + this.canPaeg.scrollTop;
    }

    if (this.isHoverscrollRight(e)) {//在滑动条上点击
        this.ScrollPosin(e);
        this.ckickScroll();
    } else if (this.isMouseHead(this.mouseData.mouseupX, this.mouseData.mouseupY)) {
        console.log('点击列头');
        e.stopPropagation();
        this.Headclick(e);
    } else if (this.dataRowColumn.isRowClcik) {
        this.actRowArr = [];
        this.getRowSelectedData(e);
    } else {
        this.actRowArr = [];
        console.log('点击内容')
        let start_time = new Date().getTime();
        console.log(start_time - new Date().getTime())
        this.getDataConstituency(e);
    }

    this.mouseData.isMousedown = false;
    this.scrollPosition.scrollRightClick = false;
    this.headRowColumn.isClcik = false;
    this.dataRowColumn.isRowClcik = false;
  }

  /**
   * 返回给定两组坐标 正确的开始结束
   * @param s_X  
   * @param s_Y   
   * @param e_X 
   * @param e_Y 
   */
  coordinateSort(s_X, s_Y, e_X, e_Y) {
    let startX = e_X <= s_X ? e_X : s_X;
    let startY = e_Y <= s_Y ? e_Y : s_Y;
    let endX = e_X >= s_X ? e_X : s_X;
    let endY = e_Y >= s_Y ? e_Y : s_Y;
    return {
      startX: startX,
      startY: startY,
      endX: endX,
      endY: endY
    }
  }
  /**
   * 获取 选中数据区域
   */
  getDataConstituency(e) {

    const is_click = this.mouseData.mousedowTime + 200 >= new Date().getTime() ? true : false;
    let EX = e.offsetX;
    let EY = e.offsetY + this.canPaeg.scrollTop;
    let canTop = this.canPaeg.scrollTop;
    if (!e.ctrlKey && !e.shiftKey) {
      this.actCellArr = [];
    }

    this.Ctx.clearRect(0, 0, this.canPaeg.width, this.canPaeg.height);
    this.act_lin.actEnd_X = EX;
    let XX = this.mouseData.mousedownX;
    let YY = this.mouseData.mousedownY + this.canPaeg.scrollTop;

    if (e.shiftKey && is_click) {
      this.act_lin.actSeart_X = this.lastCell.X;
      this.act_lin.actSeart_Y = this.lastCell.Y;
    }
    let coordinate = this.coordinateSort(this.act_lin.actEnd_X, this.act_lin.actEnd_Y, this.act_lin.actSeart_X, this.act_lin.actSeart_Y);

    let joo = {};
    this.actCellArr.forEach(item => {
      joo[item.X + "_" + item.Y] = item;
    });

    this.data_xy.forEach(linX => {
      if (linX.X + linX.W >= coordinate.startX && linX.X <= coordinate.endX) {
        linX.data.forEach(linY => {
          if (linY.Y + this.dataRowColumn.RowHeight >= coordinate.startY && linY.Y <= coordinate.endY) {
            let key = linY.X + "_" + linY.Y
            if (!joo[key]) {
              this.actCellArr.push(linY);
              joo[key] = linY;
            } else {
              if (is_click && e.ctrlKey) {
                delete joo[key];
              }
            }
          }
        })
      }
    });
    this.actCellArr = [];

    for (let n in joo) {
      this.actCellArr.push(joo[n])
    }
    joo = null;
    this.canvasDraw();
  }

  //获取选中的行
  getRowSelectedData(e) {
    const is_click = this.mouseData.mousedowTime + 200 >= new Date().getTime() ? true : false;
    let EX = e.offsetX;
    let EY = e.offsetY + this.canPaeg.scrollTop;
    let coordinate = this.coordinateSort(this.act_lin.actEnd_X, this.act_lin.actEnd_Y, this.act_lin.actSeart_X, this.act_lin.actSeart_Y);
    if (!e.ctrlKey && !e.shiftKey) {
      this.actRowArr = [];
    }

    this.data_xy[0].data.forEach((item, i) => {
      if (item.Y + this.dataRowColumn.RowHeight > coordinate.startY && item.Y < coordinate.endY) {
        this.actRowArr.push(item)
      }
    })
    this.canvasDraw();
  }

  /**
   * 绘制已选中的行
   */
  drawRowSelected() {
    this.Ctx.strokeStyle = "#5983ff";
    this.Ctx.fillStyle = "#77bfff";
    this.actCellArr = [];
    this.data_xy.forEach(item => {
      this.actRowArr.forEach(row => {
        this.actCellArr.push(item.data[row.row]);
      });
    });
    this.actCellArr.forEach(item => {
      if (this.isInsideDisplay(item.Y)) {
        this.Ctx.strokeRect(
          item.X,
          item.Y - 0.5 - this.canPaeg.scrollTop,
          item.Width,
          this.dataRowColumn.RowHeight);
        this.Ctx.fillRect(
          item.X,
          item.Y - 0.5 - this.canPaeg.scrollTop,
          item.Width,
          this.dataRowColumn.RowHeight);
      }
    });
  }
  
  /**
 * 绘制已选中单元格数据
 */
  conten_Selection() {
    if (this.act_lin.actSeart_X == null || this.act_lin.actEnd_X == null) {
      return
    }

    this.Ctx.strokeStyle = "#5983ff";
    this.Ctx.fillStyle = "#77bfff";
    this.Ctx.lineWidth = 1;
    this.actCellArr.forEach(itme => {
      if (this.isInsideDisplay(itme.Y)) {
        this.Ctx.strokeRect(
          itme.X,
          itme.Y - 1 - this.canPaeg.scrollTop,
          itme.Width,
          this.dataRowColumn.RowHeight);

        this.Ctx.fillRect(itme.X,
          itme.Y - 1 - this.canPaeg.scrollTop,
          itme.Width,
          this.dataRowColumn.RowHeight)
      }
    })
  }
  /**
   * 判断数据内容是否在可视范围内
   * @param Y 数据的Y轴起始坐标
   */
  isInsideDisplay(Y) {
    let can_Top = this.canPaeg.scrollTop;
    if ((Y - can_Top) >= 0 && (Y - can_Top) <= this.canPaeg.height) {
      return true
    } else {
      return false
    }
  }
  /**
   * 判断点击 位置是否在指定区域内
   * @param startX  区域开始的起始X坐标
   * @param startY  区域开始的起始Y坐标
   * @param endX    区域结束的起始X坐标
   * @param endY    区域结束的起始Y坐标
   * @param eX      需要判别的坐标X
   * @param eY      需要判别的坐标Y
   */
  isMouseHead(eX, eY) {
    if (
      this.canPaeg.width - this.scrollPosition.scrollRightW >= eX &&
      this.headRowColumn.RowHeight >= eY) {
      return true
    } else {
      return false;
    }
  };
  actHeadData = {
    index: null,
    type: null,
    key: null
  };
  //点击列头事件
  Headclick(e) {
    let Head = null;
    let index = 0;
    this.key_data.forEach((element, i) => {
      if (element.key != '__row' && e.offsetX > element.X && e.offsetX <= element.X + element.Width) {
        index = i;
        this.actHeadData.index = i;
        this.actHeadData.type = element.type;
        this.actHeadData.key = element.key;
        Head = element;
      }
    });


    this.dateStart=this.linSearchData[index]?this.linSearchData[index].dateStart:'';
    this.dateEnd=this.linSearchData[index]?this.linSearchData[index].dateEnd:'';
    this.actSortsSpan=this.linSearchData[index]?this.linSearchData[index].sorts:'default';
    
    this.addHeadscreen(e, Head, index);
  };

  searchInput = null;
  /**
   * listText
   * screenRowList=[{
   *    listText:array
   * }]
   * */ 
  screenRowList=[]; 
  inputKeyTime = new Date().getTime();
  delDomShow=false; //判断是否已经显示筛选框
  // 添加 搜索提示内容列表
  addSeachLise (key,data){
    key.forEach((element,n) => {
      let li_opt={};
      data[n].data.forEach((e, i) => {
        li_opt[e.text]=true;
      });
      let arr=[];
      Object.keys(li_opt).forEach(text => {
        arr.push(text);
      });
      this.screenRowList.push({listText:arr});
    });
    console.log(this.screenRowList);
  }
  /**
   * 添加div搜索
   * @param e 
   */
  addHeadscreen(e, Head, index) {
    this.li_arr=[];
    this.searchInput="";
    this.delDomShow=true;
    let para = this.el.nativeElement.querySelector('.Headscreen');
    this.ulDom=para.querySelector('ul');
    let d_w = Math.max(Head.Width, 240);
    //计算宽度
    let left = Head.X + d_w > this.canPaeg.width ? this.canPaeg.width - d_w : (Head.X);
    let div_style = {
        left: left + 'px',
        width: d_w + 'px',
        display: 'block',
        top: this.headRowColumn.RowHeight + "px",
    }
    for(let n in div_style){
      para.style[n]=div_style[n];
    }

    let numberdivDom =para.querySelector('.number-div');
    let datedivDom =para.querySelector('.date-div');
    let inputDivDom =para.querySelector('.input-text');
    
    numberdivDom.style.display='none';
    datedivDom.style.display='none';
    inputDivDom.style.display='none';
    this.ulDom.style.display='none';
    if(Head.type=='number'||Head.type=='money'){
      numberdivDom.style.display='block';
    }
    if(Head.type=='date'){
      datedivDom.style.display='block';
    }
    if(Head.type=='str'){
      inputDivDom.style.display='block';
      this.ulDom.style.display='block';
    }

    let inputs=para.querySelector('.input-text');

    this.inputKeyTime = new Date().getTime();
    inputs.addEventListener('focus', (e) => {
      this.inputKeyTime = new Date().getTime();
    });
    //按钮
  };

  resetButton(){
    this.dateStart="";
    this.dateEnd="";
    this.searchInput="";
    this.actSortsSpan='default';
    this.li_arr=[];
  }
  screenInputkeydown(e){
    this.inputKeyTime = new Date().getTime();
    setTimeout(() => {
      if (this.inputKeyTime + 400 <= new Date().getTime()) {
        console.log(new Date().getTime() - this.inputKeyTime + 1000 - 500);
        this.inputKeyTime = new Date().getTime();
        this.actHeadData.index;
        this.inputFilter();
      }
    }, 400);
  }

  // 筛选符合搜索条件的类
  ulDom = null;
  li_arr=[];

  inputFilter() {
    this.actHeadData.index;
    this.li_arr = [];
    if(this.searchInput){
      this.screenRowList[this.actHeadData.index].listText.forEach((e) => {
        if (e.includes(this.searchInput)) {
          this.li_arr.push(e);
        }
      });
    }
    this.li_arr.length=Math.min(500,this.li_arr.length);

  };
  ulDomliClick(e){
    let is_true= eval(e.srcElement.getAttribute('checkbox'));
    e.srcElement.setAttribute('checkbox',!is_true);
  }

  //确定筛选事件
  screenOk() {
    //有筛选条件时 将筛选要素 插入对象当中  如果没有筛选就清空筛选条件
    let delDom = this.el.nativeElement.querySelector('.Headscreen');
    
    let list=delDom.querySelectorAll('li[checkbox=true]');
    let numberMinAndMax=delDom.querySelectorAll('input[type="number"]');
    console.log(numberMinAndMax);
    let listText=[];
    if(list.length>0){
      list.forEach(element => {
        listText.push(element.innerText);
      });
    }
    console.log(this.dateStart,this.dateEnd);
    //设置筛选条件
    // this.linSearchData[this.actHeadData.index] = null;
    this.linSearchData.forEach(element => {
      if(element.sorts){
        element.sorts='default';
      }
    });

    if (this.searchInput != ""||list.length>0) {
      this.linSearchData[this.actHeadData.index] = {
        searchInput: this.searchInput,  //模糊匹配输入的文字 输入框搜索
        type: this.actHeadData.type,    
        key: this.actHeadData.key,
        list:listText,                        // 精确匹配选中的类型
        numberMinAndMax:listText,              // 数值类型匹配筛选最大值最小值
        dateStart:this.dateStart ,
        dateEnd:this.dateEnd,
        sorts:this.actSortsSpan
      };
    }
    if(this.actHeadData.type=='date'&&(this.dateStart||this.dateEnd)){
      this.linSearchData[this.actHeadData.index] = {
        searchInput: this.searchInput,        //模糊匹配输入的文字 输入框搜索
        type: this.actHeadData.type,    
        key: this.actHeadData.key,
        list:listText,                        // 精确匹配选中的类型
        numberMinAndMax:listText,             // 数值类型匹配筛选最大值最小值
        dateStart:this.dateStart,             // 筛选的日期开始时间
        dateEnd:this.dateEnd,                 // 筛选的日期结束时间
        sorts:this.actSortsSpan               //排序 default：默认  down：正序 upward 倒序
      };
    }
    if(this.actSortsSpan!=='default'){
      this.linSearchData[this.actHeadData.index] = {
        searchInput: this.searchInput,        //模糊匹配输入的文字 输入框搜索
        type: this.actHeadData.type,    
        key: this.actHeadData.key,
        list:listText,                        // 精确匹配选中的类型
        numberMinAndMax:listText,             // 数值类型匹配筛选最大值最小值
        dateStart:this.dateStart,             // 筛选的日期开始时间
        dateEnd:this.dateEnd,                 // 筛选的日期结束时间
        sorts:this.actSortsSpan               //排序 default：默认  down：正序 upward 倒序
      };
    } 

    //清除元素
    if (delDom) {
      delDom.style.display="none";
      // this.el.nativeElement.removeChild(delDom);
    };

    this.canPaeg.scrollTop = 0;
    this.scrollPosition.scrollRightY = this.headRowColumn.RowHeight;

    this.ResetCanvas();
    this.totalDate = [];
    this.data_xy.forEach((e, i) => {
      let text = this.Calculate_total(e.data, this.key_data[i]);
      this.key_data[i]['total'] = text;
      this.totalDate.push(text);
    });
    this.canvasDraw();
  }


  //是否选中第一列
  isRowLeft(e) {
    if (e.offsetY > this.headRowColumn.RowHeight && e.offsetX < this.key_data[0].Width) {
      return true
    } else {
      return false
    }
  }

  /**
   *  鼠标位置是否再滚动条上 判断是否hover在
   * cursor:pointer;
   * */
  isHoverscrollRight(e) {
    if ((e.offsetX > this.scrollPosition.scrollRightX && e.offsetY > this.headRowColumn.RowHeight)
      && (e.offsetX < this.scrollPosition.scrollRightX + this.scrollPosition.scrollRightW && e.offsetY < this.canPaeg.height - this.footRowColumn.RowHeight)
    ) {
      return true
    } else {
      return false
    }
  }

  /**
   * 鼠标移出画布
   * @param `e` event对象
   * */
  mouseoutCanvas(e) {
    // this.scrollPosition.scrollRightW = 10;
    this.scrollPosition.scrollRightHover = false;
    this.mouseData.isMousedown = false;
    this.Ctx.clearRect(0, 0, this.canPaeg.width, this.canPaeg.height);
    this.canvasDraw();
  }
  /**
   * 数据内容区域 事件处理
   */
  conten_(e) {
    this.act_lin.actSeart_Y = e.offsetY + this.canPaeg.scrollTop;
    this.act_lin.actSeart_X = e.offsetX;
  };

  /**
   * @param
   */
  scrollTop = 0;
  scrollLeft = 0;


  //在滑动框上点击
  ckickScroll() {
    this.Ctx.clearRect(0, 0, this.canPaeg.width, this.canPaeg.height);
    this.canvasDraw();
  }
  /**
   * 拖动下拉滑动块
   * @param `e`  event对象
   **/
  mousemoveScroll(e) {
    let aa = this.mouseData.mousedownX > this.scrollPosition.scrollRightX &&
      this.mouseData.mousedownX < this.scrollPosition.scrollRightX + this.scrollPosition.scrollRightW &&
      this.mouseData.mousedownY > this.headRowColumn.RowHeight &&
      this.mouseData.mousedownY < this.canWH.contenH - this.headRowColumn.RowHeight - this.footRowColumn.RowHeight;

    if (!this.mouseData.isMousedown) {
      return
    }
    this.ScrollPosin(e);
    this.scrollPosition.scrollRightHover = true;
    this.Ctx.clearRect(0, 0, this.canPaeg.width, this.canPaeg.height);
    this.canvasDraw();
  }

  /**
   * 根据鼠标位置确定滚动条位置
   * @param e 
   */
  ScrollPosin(e) {
    this.scrollPosition.scrollRightY = e.offsetY;
    this.scrollPosition.scrollRightY = this.scrollPosition.scrollRightY > this.headRowColumn.RowHeight ? this.scrollPosition.scrollRightY : this.headRowColumn.RowHeight;
    this.scrollPosition.scrollRightY = this.scrollPosition.scrollRightY <= this.canPaeg.height - this.footRowColumn.RowHeight - this.scrollPosition.scrollRightH ? this.scrollPosition.scrollRightY : this.canPaeg.height - this.scrollPosition.scrollRightH - this.footRowColumn.RowHeight;
    // 页面 百分百
    let is_scrollRightH = (this.scrollPosition.scrollRightY - this.headRowColumn.RowHeight) / (this.canPaeg.height - this.headRowColumn.RowHeight - this.scrollPosition.scrollRightH - this.footRowColumn.RowHeight);
    is_scrollRightH = is_scrollRightH > 1 ? 1 : is_scrollRightH;
    this.canPaeg.scrollTop = Math.round(is_scrollRightH * (this.canWH.contenH - this.canPaeg.height + this.headRowColumn.RowHeight));
  };

  /**
   * 绘制滚动条
   * @param `X` X坐标位置
   * @param `Y` Y坐标位置
   * @param `W` 下拉框宽度
   * @param `H` 下拉框高度
   * */
  Draw_scroll(X, Y, W, H, AbnormalArr) {
    // AbnormalArr
    let scroll_conH = this.canPaeg.height - this.headRowColumn.RowHeight - this.footRowColumn.RowHeight;
    let row_h = scroll_conH / this.data_xy[0].data.length;
    row_h = Math.max(0.5, row_h);
    row_h = Math.min(3, row_h);


    this.Ctx.fillStyle = "#f1f1f1";
    this.Ctx.fillRect(this.canPaeg.width - this.scrollPosition.scrollRightW, 0, this.scrollPosition.scrollRightW, this.canPaeg.height);
    this.Ctx.fillStyle = "#d3d3d3";
    AbnormalArr.forEach(item => {
      item.forEach(itemY => {
        this.Ctx.fillStyle = "#ff6d6d";
        let item_top = Math.ceil((itemY / this.data_xy[0].data.length) * scroll_conH) - 0.5;
        this.Ctx.fillRect(this.canPaeg.width - this.scrollPosition.scrollRightW, this.headRowColumn.RowHeight + item_top, this.scrollPosition.scrollRightW, row_h);
      })
    });
    this.Ctx.fillStyle = "rgba(100, 100, 100, 0.5)";
    this.Ctx.fillRect(X, Y, W, H);
  };

  footDraw() {
    let key_linX = 0.5;
    this.Ctx.font = "16px serif";
    this.Ctx.strokeStyle = "#d3d3d3";
    this.Ctx.fillStyle = "#000";
    this.Ctx.textBaseline = 'middle'; //上下对齐方式
    let t_Y = this.canPaeg.height - this.footRowColumn.RowHeight;
    let opt = {};
    this.actCellArr.forEach(item => {
      opt[item.lin] ? opt[item.lin].push(item) : opt[item.lin] = [item];
    })

    this.key_data.forEach((item, i) => {
      let text: any = "";
      if (opt[i]) {
        text = this.Calculate_total(opt[i], item);
      } else {
        text = this.totalDate[i];
      }

      this.Ctx.fillStyle = "#f3f3f3";
      this.Ctx.fillRect(key_linX, t_Y, item.Width, this.headRowColumn.RowHeight);
      this.Ctx.fillStyle = "#000";
      this.Ctx.strokeRect(key_linX, t_Y, item.Width, this.headRowColumn.RowHeight);
      this.Ctx.fillStyle = "#000";
      this.Ctx.textAlign = item.textAlign;
      if (item.textAlign == 'center') {
        this.Ctx.fillText(text, key_linX + item.Width / 2, t_Y + this.footRowColumn.RowHeight / 2);
      } else if (item.textAlign == 'right') {
        this.Ctx.fillText(text, key_linX + item.Width - 5, t_Y + this.footRowColumn.RowHeight / 2);
      } else {
        this.Ctx.fillText(text, key_linX + 5, t_Y + this.footRowColumn.RowHeight / 2);
      }
      key_linX += item.Width;
    });
  }

  //计算类别，数量
  Calculate_total(data, item) {
    let nums = 0;
    if (!item.type) {
      let opt = {};
      data.forEach(element => {
        opt[element.text] = true;
      });
      let i = 0;
      for (let n in opt) {
        i++;
      }
      return i + '类';
    }
    if (item.type == 'money') {
      data.forEach(element => {
        let num = element.text.toString();
        num = parseFloat(num.replace(/,/g, ""))
        nums += num
      });
      return nums
    } else if (item.type == 'number') {
      data.forEach(element => {
        let num: any = element.text.toString();
        num = parseFloat(num.replace(/,/g, ""));
        nums += num
      });
      return nums.toFixed(2);
    } else if (item.key == '__row') {
      return ""
    } else {
      let opt = {};
      data.forEach(element => {
        opt[element.text] = true;
      });
      let i = 0;
      for (let n in opt) {
        i++;
      }
      return i + '类';
    }
  }
  /**
   * 滚动条事件
   * */
  wheelCanvas(e) {
    this.Ctx.clearRect(0, 0, this.canPaeg.width, this.canPaeg.height);
    this.canPaeg.scrollTop += parseInt(e.deltaY);
    this.canPaeg.scrollTop = this.canPaeg.scrollTop < 0 ? 0 : this.canPaeg.scrollTop;
    let max_height = this.canWH.contenH - this.canPaeg.height + this.headRowColumn.RowHeight;
    this.canPaeg.scrollTop = this.canPaeg.scrollTop > max_height ? max_height : this.canPaeg.scrollTop;

    let percentage = this.canPaeg.scrollTop / (this.canWH.contenH - this.canPaeg.height);

    percentage = percentage > 1 ? percentage : percentage;
    this.scrollPosition.scrollRightY = this.headRowColumn.RowHeight + percentage * (this.canPaeg.height - this.headRowColumn.RowHeight - this.scrollPosition.scrollRightH - this.footRowColumn.RowHeight);

    this.canvasDraw();
  };

  DownloadCsvDraw(start, end) {
    this.canWH.canW
    let x = this.canPaeg.width - 10;
    let y = this.canPaeg.height - 15;
    let lin = 1;

    this.Ctx.moveTo(x - 4, y - 4);
    this.Ctx.lineTo(x + 4, y - 4);

    this.Ctx.lineTo(x + 4, y);
    this.Ctx.lineTo(x + 8, y);

    this.Ctx.lineTo(x, y + 10);

    this.Ctx.lineTo(x - 8, y);
    this.Ctx.lineTo(x - 4, y);
    this.Ctx.fill();

    // this.Ctx.lineTo(W, lin_y - this.canPaeg.scrollTop);
    this.Ctx.stroke();
  }
  isDownloadCsv(e) {
    if (
      e.offsetX > this.canPaeg.width - this.scrollPosition.scrollRightW &&
      e.offsetY > this.canPaeg.height - this.scrollPosition.scrollRightH
    ) {
      return true;
    } else {
      return false;
    }
  }
  downloadCsv() {
    const BOM = '\uFEFF';
    const output = this.data;
    let str = "";
    this.key_data.forEach(aa => {
      if (aa.isdownload) {
        str += aa.text;
        str += ","
      }
    });
    str += '\n'
    this.data.forEach((item, i) => {
      this.key_data.forEach(aa => {
        if (aa.isdownload) {
          str += item[aa.key]
          str += ","
        }
      })
      str += '\n'
    })
    var blob = new Blob([BOM + str], { type: 'text/csv' });
    const name = 'aaa';
    if (navigator.msSaveOrOpenBlob) {
      navigator.msSaveOrOpenBlob(blob, `${name}.csv`)
    } else {
      let downloadLink = document.createElement('a');
      downloadLink.setAttribute('href', URL.createObjectURL(blob))
      // 因为url有最大长度限制，encodeURI是会把字符串转化为url，超出限制长度部分数据丢失导致下载失败,为此我采用创建Blob（二进制大对象）的方式来存放缓存数据，具体代码如下：
      downloadLink.download = `${name}.csv`
      document.body.appendChild(downloadLink)
      downloadLink.click()
      document.body.removeChild(downloadLink)
    }
  }

}
